home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Pattern Parser package for LPmud, JnA 1990
-
- Ver 2.0
-
- If you have questions or complaints about this code please refer them
- to jna@cd.chalmers.se
-
- This is the old version of parse_command() used in compatibility mode.
-
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #include "lint.h"
- #include "interpret.h"
- #include "config.h"
- #include "object.h"
- #include "wiz_list.h"
-
- #define VALUE struct svalue
- #define OBJECT struct object
- #define VECTOR struct vector
- #define SVALUE struct svalue
- #define LVALUE struct svalue
-
- extern char *string_copy PROT((char *)), *xalloc PROT((int));
- extern int o_flag, d_flag; /* for debugging purposes */
- extern SVALUE const0, const1;
-
- #ifndef tolower /* On some systems this is a function */
- extern int tolower PROT((int));
- #endif
-
- #ifdef COMPAT_MODE
- /*****************************************************
-
- This is the parser
-
-
- Left to do 910723:
-
- Fix so alternatives possible after %s in a pattern
-
- */
- /*
- Doc for LPC function
-
- int parse_command(string,ob/arr,string,destargs...)
-
- parse Returns 1 if pattern matches
-
- string Given command
- ob/arr if arr
- array holding the accessible objects
- if ob
- object from which to recurse and create
- the list of accessible objects, normally
- ob = environment(this_player())
- string Parsepattern as list of words and formats:
- Example string = " 'get' / 'take' %i "
- Syntax:
- 'word' obligatory text
- [word] optional text
- / Alternative marker
- %o Single item, object
- %l Single living object
- %s Any text
- %w Any word
- %p Preposition
- %i Any items
- %d Number 0- or tx(0-99)
-
- destargs This is the list of result variables as in sscanf
- One variable is needed for each %_
- The return types of different %_ is:
- %o Returns an object
- %l Returns an object
- %s Returns a string of words
- %w Returns a string of one word
- %p Can on entry hold a list of word in array
- or an empty variable
- Returns:
- if empty variable: a string
- if array: array[0]=matched word
- %i Returns a special array on the form:
- [0] = (int) +(wanted) -(order) 0(all)
- [1..n] (object) Objectpointers
- %d Returns a number
-
- Example:
-
- parse_command("take apple",environment(this_player()),
- " 'get' / 'take' %i ",items);
-
-
- */
-
- /* Hardcoded function names to call in LPC objects
- */
- #define QIDFUNC "id" /* Func to query in objects to ack name */
- #define QPLURIDFUNC "plural_id" /* As Id but pluralform of name */
- #define QADJFUNC "adjectiv_id" /* As Id but ack adjectiv not name */
- #define QSHORTFUNC "short" /* Objects shortdescription */
-
- #define EQ(x,y) (strcmp(x,y)==0)
- #define EQN(x,y) (strncmp(x,y,strlen(x))==0)
- #define EMPTY(x) (strcmp(x,"")==0)
- #define COPY(x) (strcpy((char*)xalloc(strlen(x)+1),x))
-
- #define KLUDGELEN 200 /* How long should strings be */
-
- struct altern_objects {
- OBJECT *ao_obj;
- struct altern_objects *next;
- };
-
- int gDebug=0;
- char gMword[KLUDGELEN]; /* Text inom '' och [] */
- char gFword[KLUDGELEN]; /* Temp word gotten by getfirst() */
- struct altern_objects *gOblist; /* List of accessible objects */
- char gAdjective[4*KLUDGELEN]; /* all adjectives before objname */
- LVALUE *gCarg; /* Current argument to %_ */
- int gWantnum; /* Number of wanted items 0 = all */
- struct altern_objects *gPobjects; /* List of parsed objects */
- LVALUE *gTxarg; /* Argument of LPCvariable to store %s */
- LVALUE *gForprepos; /* Save arg* here for findprepos */
- LVALUE *gTopStack; /* arg* to arg after my last */
-
- #define EP 0 /* End Parse marker */
- #define SI 1 /* %o single item */
- #define IT 2 /* %i items */
- #define US 3 /* %l single living object */
- #define PP 4 /* %p prepositions */
- #define TX 5 /* %s string of words */
- #define DTX 6 /* 'word' */
- #define OTX 7 /* [word] */
- #define ALT 8 /* / alternates */
- #define W1 9 /* %w string of one word */
- #define NUM 10 /* %d integer */
-
- /* Search string in reverse order, I should replace it with strrchr I know :)
- */
- char *backstrchr (apa, ch)
- char *apa;
- char ch;
- {
- char *sp;
-
- sp = &apa[strlen(apa)];
- while (sp>apa) {
- if (*sp==ch) return sp+1;
- sp--;
- }
- return 0;
- }
-
- /* Convert string to lowercase
- */
- char *lowercase (apa)
- char *apa;
- {
- char *bepa;
-
- bepa = apa;
- while (*bepa) {
- if ((*bepa>'A') && (*bepa<'a')) (*bepa)+='a'-'A';
- bepa++;
- }
- return apa;
- }
-
- /* Add all objects in the inventory of 'first' and itself to the list 'parent'
- antal holds the number of elements in the 'parent' list.
- */
- void fixlist (first, parent, antal)
- OBJECT *first;
- struct altern_objects **parent;
- int *antal;
- {
- OBJECT *cur;
- struct altern_objects *this,*taill;
- cur=first; this= *parent;
- if (!cur) return;
- while (cur) {
- if (cur->contains) fixlist(cur->contains,&this,antal);
- taill=this;
- this=(struct altern_objects *) xalloc(sizeof(struct altern_objects));
- this->ao_obj=cur; (*antal)++;
- add_ref(cur,"parse->fixlist");
- if (gDebug) fprintf(stderr," Obj:%s ,",cur->name);
- this->next=taill; cur=cur->next_inv;
- }
- *parent=this;
- }
-
- /* Create a list of the theoretically accessible objects from 'src'
- */
- int makeobjlist (alist, src)
- struct altern_objects **alist;
- OBJECT *src;
- {
- OBJECT *env,*cur;
- struct altern_objects *this;
- int cnt;
- *alist=0;
- if (!src) env=command_giver->super;
- else env=src;
- if (!env) return 0;
- if (gDebug) fprintf(stderr,"Make list: %s\n",env->name);
- if (!(env->contains)) return 0;
- cur=env->contains;
- this=0; cnt=0;
- fixlist(cur,&this,&cnt); *alist=this;
- return cnt;
- }
-
- /* Routines to use for alternate filters
- */
-
- /* Return number of objects in the list
- */
- int itnumalt()
- {
- int ant;
- struct altern_objects *ao;
-
- ant=0; ao=gPobjects;
- while (ao) {
- ant++;
- ao=ao->next;
- }
- return ant;
- }
-
- /* Return a pointer to the numbered element of the list
- */
- OBJECT *italt (a)
- int a;
- {
- int ant;
- struct altern_objects *ao;
-
- ant=0; ao=gPobjects;
- while (ao) {
- ant++;
- if (ant==a) return ao->ao_obj;
- ao=ao->next;
- }
- return 0;
- }
-
- /* Free the list, parameter bas is obsolete
- */
- void italt_new ()
- {
-
- /* Free p} altern_objects listan */
- struct altern_objects *ao;
- struct altern_objects *ao2;
-
- if (gDebug) fprintf(stderr,"Clearing italt\n");
- ao2=ao=gPobjects; gPobjects=0;
- while (ao) {
- ao=ao->next;
- free_object(ao2->ao_obj,"parse->italt_new()");
- xfree((char *)ao2);
- ao2=ao;
- }
- }
-
- /* Create the list as all the theoretically accessible objects
- */
- void italt_loadall()
- {
- if (gPobjects) italt_new();
- makeobjlist(&gPobjects,0);
- }
-
- /* Put an object at the end of the list
- */
- void italt_put (obj)
- OBJECT *obj;
- {
- struct altern_objects *ao,*old;
-
- if (gDebug) fprintf(stderr,"Putting: %s",obj->name);
- ao=gPobjects; old=ao;
- while (ao) {
- old=ao; ao=ao->next;
- }
- ao=(struct altern_objects *) xalloc(sizeof(struct altern_objects));
- if (old) old->next=ao;
- else gPobjects=ao;
- ao->ao_obj=obj; ao->next=0;
- add_ref(obj,"parse->italt_put()");
- if (gDebug) fprintf(stderr,"..done\n");
- }
-
-
- /* Put first word of cmd in gFword and point to next word
- */
- char *getfirst (cmd)
- char **cmd;
- {
- int pos,inqoute;
- char ch,*st;
-
- st= *cmd; strcpy(gFword,""); if (st[0]==0) return gFword;
- ch=' '; pos=0; inqoute=0;
- while ((st[0]<=' ') && (st[0])) st++; /* Skip leading spaces */
- if ((st[0]=='\'') || (st[0]=='[')) {
- inqoute=1; ch=st[0]; gFword[0]=st[0]; pos=1; st++;
- }
- if (ch=='[') ch=']';
- while ((pos<(KLUDGELEN-1)) && (st[0]) && (st[0]!=ch)) {
- gFword[pos++]=st[0]; st++;
- if ((st[0]) && (st[0]<' ')) st[0]=' '; /* Replace ctrl chars */
- }
- if ((inqoute) && (pos<(KLUDGELEN-1))) {
- gFword[pos++]=ch; if (st[0]) st++;
- }
- gFword[pos]=0; /* fprintf(stderr,"{%s}",gFword); */
- *cmd=st;
- return gFword;
- }
-
- /* Put first word of cmd in gFword
- without incrementing the callers pointer in the command string
- */
- char *lookfirst (cmd)
- char *cmd;
- {
- return getfirst(&cmd);
- }
-
- /* Call object function in LPC
- */
- int call_obj (fnamn, on, apa)
- char *fnamn;
- OBJECT *on;
- char *apa;
- {
- struct svalue *ret;
-
- if (gDebug) fprintf(stderr,"Calling %s in %s with %s\n",fnamn,on->name,apa);
- push_constant_string(apa);
- ret = apply(fnamn,on,1);
- if (!ret) return 0;
- if ( ret->type == T_NUMBER) return ret->u.number;
- return 0;
- }
-
- /* Change a noun in pluralform to a noun in singularform
- */
- char *singfix (str)
- char *str;
- {
- static char sing[KLUDGELEN];
- char *sp;
- int sl;
-
- sl=strlen(str); if (sl<2) return str;
- sp= &str[sl-3]; strcpy(sing,str); sing[sl-3]=0;
- if (gDebug) fprintf(stderr,"To singular (%s) end(%s) begin(%s)\n",str,sp,sing);
- if (EQ(str,"corpses")) return "corpse";
- if (EQ(sp,"ses")) return strcat(sing,"s");
- else if (EQ(sp,"xes")) return strcat(sing,"x");
- else if (EQ(sp,"hes")) return strcat(sing,"h");
- else if (EQ(sp,"ies")) return strcat(sing,"y");
- else if (EQ(sp,"ves")) return strcat(sing,"fe");
- else if (sp[2]=='s') {
- strcat(sing,sp); sing[sl-1]=0;
- return sing;
- }
- if (EQ(str,"teeth")) return "tooth";
- if (EQ(str,"feet")) return "foot";
- if (EQ(str,"men")) return "man";
- if (EQ(str,"women")) return "woman";
- if (EQ(str,"children")) return "child";
- if (EQ(str,"sheep")) return "sheep";
- return str;
- }
-
- /* Checks with obj in gOblist to see if it accepts all gAdjectives in adjs
- Used when name of object not known, i.e cmds like: 'get all the red ones'
- if func QADJFUNC doesn't exist in obj last word of QSHORTFUNC is used
- as object name and set as suffix to the adjective in call to id()
- */
- int matchadjective (adjs)
- char *adjs;
- {
-
- char ad[KLUDGELEN],tot[2*KLUDGELEN],*sp,*sp2;
- struct altern_objects *ao;
- OBJECT *on;
- struct svalue *ret;
-
- ao=gOblist;
- while (ao) {
- on=ao->ao_obj;
- sp=adjs;
- while ((on) && (sp) && (*sp)) {
- while (*sp==' ') sp++;
- sp2=strchr(sp,' ');
- if (sp2) {
- *sp2=0;
- strcpy(ad,sp); *sp2=' '; sp=sp2;
- if (!call_obj(QADJFUNC,on,ad)) on=0; /* Not ok */
- }
- sp=sp2;
- }
- if (on) italt_put(on);
- else {
- on=ao->ao_obj;
- ret = apply(QSHORTFUNC,on,0);
- if (ret->type==T_STRING) {
- sp=ret->u.string; sp2=backstrchr(sp,' ');
- if (sp2) sp=sp2;
- sprintf(tot,"%s%s",adjs,sp); lowercase(tot);
- if (!call_obj(QIDFUNC,on,tot)) on=0;
- }
- else on=0;
- }
- if (on) italt_put(on);
- ao=ao->next;
- }
- return itnumalt();
- }
-
- /* Decide if a word is a general word of type: those, ones
- */
- int check_for_general (onam, plur)
- char *onam;
- int plur;
- {
-
- static char* plurpron[] = {"those","them","these","ones","$"};
- static char* singpron[] = {"this","one","it","$"};
- int ilop;
-
- if (EMPTY(onam)) return 0;
- if (plur) {
- ilop=0;
- while (!EQ(plurpron[ilop],"$")) if (EQ(plurpron[ilop++],onam)) return 1;
- }
- else {
- ilop=0;
- while (!EQ(singpron[ilop],"$")) if (EQ(singpron[ilop++],onam)) return 1;
- }
- return 0;
- }
-
- int order_num (wd)
- char *wd;
- { /* Only positive numbers and zero */
-
- static char *onums[] = {"first","second","third","fourth","fifth","sixth",
- "seventh","eighth","nineth","tenth",
- "eleventh","twelfth","thirteenth","fourteenth","fifteenth","sixteenth",
- "seventeenth","eighteenth","nineteenth","dummy"};
- static char *onumt[] = {"twenty","thirty","forty","fifty","sixty","seventy",
- "eighty","ninety"};
- static char *onumta[] = {"twentieth","thirtieth","fortieth","fiftieth","sixtieth","seventieth",
- "eightieth","ninetieth"};
-
- char ns[KLUDGELEN];
-
- int ilop,nm;
-
- if (EMPTY(wd)) return -1;
- for (ilop=1;ilop<20;ilop++) {
- if (EQ(onums[ilop-1],wd)) return ilop;
- }
- for (nm=0;nm<8;nm++) for (ilop=0;ilop<9;ilop++) {
- if (ilop>0) {
- sprintf(ns,"%s%s",onumt[nm],onums[ilop-1]);
- if (EQ(ns,wd)) return 20+nm*10+(ilop);
- } else
- if (EQ(onumta[nm],wd)) return 20+nm*10+(ilop);
- }
- return -1;
- }
-
- int numeric (wd)
- char *wd;
- { /* Only positive numbers and zero */
-
- static char *nums[] = {"one","two","three","four","five","six",
- "seven","eight","nine","ten",
- "eleven","twelve","thirteen","fourteen","fifteen","sixteen",
- "seventeen","eighteen","nineteen"};
- static char *numt[] = {"twenty","thirty","forty","fifty","sixty","seventy",
- "eighty","ninety"};
-
- char ns[KLUDGELEN];
-
- int ilop,nm;
-
- if (EMPTY(wd)) return -1;
- if (sscanf(wd,"%d",&nm)) return (nm>=0) ? nm : -1;
- if ((EQ(wd,"a")) || (EQ(wd,"an"))) return 1;
- for (ilop=1;ilop<20;ilop++) if (EQ(nums[ilop-1],wd)) return ilop;
- for (nm=0;nm<8;nm++) for (ilop=0;ilop<9;ilop++) {
- if (ilop>0) {
- sprintf(ns,"%s%s",numt[nm],nums[ilop-1]);
- if (EQ(ns,wd)) return 20+nm*10+(ilop);
- }
- else
- if (EQ(numt[nm],wd)) return 20+nm*10+(ilop);
- }
- return -1;
- }
-
- /* Searches commandstring for "adj1 adj2 ... adjN objectname"
- Stores words before name in string: gAdjective, as "adj1 adj2 adj3 "
- */
- OBJECT *matchobject2 (cmd, plur)
- char **cmd;
- int plur;
- {
- OBJECT *on;
- struct altern_objects *ao;
- char *st,*ocmd,totname[2*KLUDGELEN],tot2[2*KLUDGELEN];
-
- ocmd= *cmd; strcpy(gAdjective,"");
- st=lowercase(getfirst(cmd));
- while (st[0]) {
- if (check_for_general(st,plur)) {
- if (matchadjective(gAdjective)) return italt(1);
- }
- sprintf(totname,"%s%s",gAdjective,st);
- if (plur) sprintf(tot2,"%s%s",gAdjective,singfix(st));
- ao=gOblist;
- while (ao) {
- on=0;
- if (plur) {
- if (call_obj(QPLURIDFUNC,ao->ao_obj,totname)) on=ao->ao_obj;
- else if (call_obj(QIDFUNC,ao->ao_obj,tot2)) on=ao->ao_obj;
- }
- else if (call_obj(QIDFUNC,ao->ao_obj,totname)) on=ao->ao_obj;
- if (on) italt_put(on);
- ao=ao->next;
- }
- if (!itnumalt()) {
- strcat(gAdjective,st); strcat(gAdjective," ");
- st=lowercase(getfirst(cmd));
- }
- else st[0]=0;
- }
- if (itnumalt()) return italt(1);
- *cmd=ocmd; return 0;
- }
-
- /* Search the command for valid object description
- */
- OBJECT *finditem (cmd, plur)
- char **cmd;
- int plur;
- {
- int nm;
- OBJECT *pn;
- char *ocmd,w1[KLUDGELEN];
-
- ocmd= *cmd; strcpy(w1,lowercase(getfirst(cmd)));
- if (gDebug) fprintf(stderr,"FO (plur=%d): %s\n",plur,ocmd);
- italt_new(); /* Clear alternate list */
- gWantnum=1; /* Antal objekt som anv{ndaren vill ta */
- if (EMPTY(w1)) {
- *cmd=ocmd;
- return 0;
- }
-
- /* Must be hardcode skipped for recursive with plural
- */
- if (EQ("the",w1)) {
- if (gDebug) fprintf(stderr,"Skip 'the'\n");
- *cmd=ocmd; getfirst(cmd);
- if ((pn=finditem(cmd,plur))) return pn;
- else { *cmd=ocmd; return 0; }
- }
-
- /* Check things like: some <objname>
- */
- else if ((EQ("some",w1)) && (plur==0)) {
- *cmd=ocmd; getfirst(cmd);
- /* Skip of in : some of the bottles */
- if (EQ(lowercase(lookfirst(*cmd)),"of")) getfirst(cmd);
-
- nm = random_number(6) + 2; /* some objects are random:2-7 */
- if (gDebug) fprintf(stderr,"some rnd = %d\n",nm);
- if ((pn=finditem(cmd,1))) {
- gWantnum=nm;
- return pn;
- }
- }
-
- /* Check things like: three <objname>
- */
- else if ( (plur==0) && ((nm=numeric(w1))>0) ) {
- if (gDebug) fprintf(stderr,"Numeral: %d (%s)\n",nm,w1);
- *cmd=ocmd; getfirst(cmd);
- /* Skip of in : two of the bottles */
- if (EQ(lowercase(lookfirst(*cmd)),"of")) getfirst(cmd);
- if ((pn=finditem(cmd,nm-1))) {
- gWantnum=nm; return pn;
- }
- }
-
- /* Check things like: third <objname>
- */
- else if ( (plur==0) && ((nm=order_num(w1))>0) ) {
- if (gDebug) fprintf(stderr,"Order: %d (%s)\n",nm,w1);
- *cmd=ocmd; getfirst(cmd);
- /* Skip of in : second of the bottles */
- if (EQ(lowercase(lookfirst(*cmd)),"of")) {
- getfirst(cmd);
- if ((pn=finditem(cmd,1))) { /* Fix second of the bottles */
- gWantnum= -nm; return pn;
- }
- }
- else {
- if ((pn=finditem(cmd,0))) { /* Fix second bottle */
- gWantnum = -nm; return pn;
- }
- }
- }
-
-
- /* Check things like: all <objname>
- */
- else if ((EQ("all",w1)) && (plur==0)) {
- if (gDebug) fprintf(stderr,"All found\n");
- *cmd=ocmd; getfirst(cmd);
- /* Skip of in : all of the bottles */
- if (EQ(lowercase(lookfirst(*cmd)),"of")) { getfirst(cmd); }
- if ((pn=finditem(cmd,1))) { /* Handle: get all apples */
- gWantnum=0; /* Antal objekt som anvandaren vill ta 0 == all */
- return pn;
- }
- else { /* Handle: get all */
- italt_loadall(); pn=(OBJECT *) italt(1);
- gWantnum=0; /* Antal objekt som anvandaren vill ta 0 == all */
- }
- }
-
- /* Search for: adj1 adj2 ... adjN objectname
- */
- else {
- *cmd=ocmd; if (gDebug) fprintf(stderr,"Objtry: %s\n",ocmd);
- if (plur) pn=matchobject2(cmd,plur);
- else { /* Standard singular */
- pn=matchobject2(cmd,0);
- if (!pn) { /* Handle things of type: get apples */
- pn=matchobject2(cmd,1);
- if (pn) gWantnum = 0; /* Default this to all */
- }
- }
- if (gDebug) fprintf(stderr,"Done matchobject in finditem.\n");
- }
-
- if (pn == 0) *cmd=ocmd;
- if (gDebug) fprintf(stderr,"Done finditem.\n");
- return pn;
- }
-
- /* Find match to a %i in pattern
- */
- int findobject (cmd)
- char **cmd;
- {
- int nm,s;
- OBJECT *ob;
-
- if (finditem(cmd,0)) {
- if (gCarg) {
- VECTOR *p;
- if (gDebug) fprintf(stderr,"Assign array\n");
- nm=itnumalt();
- p=(VECTOR *)allocate_array(nm+1);
- p->item[0].type = T_NUMBER;
- p->item[0].u.number = gWantnum;
-
- /* Make array in reverse order from italt() because
- makeobjlist() has reversed the order on entry
- */
- for (s=1;s<=nm;s++) {
- p->item[s].type = T_OBJECT;
- p->item[s].u.ob = ob = italt(nm+1-s);
- if (!ob) if (gDebug) fprintf(stderr,"No object from italt %d\n",s);
- if (ob) add_ref(ob,"parse_command");
- }
- free_svalue(gCarg->u.lvalue);
- gCarg->u.lvalue->type = T_POINTER;
- gCarg->u.lvalue->u.vec = p;
- gCarg->u.lvalue->u.vec->ref++;
-
- if (gDebug) fprintf(stderr,"Assign array2\n");
- }
- return 1;
- }
- return 0;
- }
-
- /* Find match to a %l in pattern
- */
- OBJECT *findplay (cmd)
- char **cmd;
- {
- OBJECT *pn;
- char w1[KLUDGELEN];
-
- strcpy(w1,lowercase(lookfirst(*cmd)));
- /* can be fixed later with call to LPC command_giver->query_real_name()
- if (EQ(w1,"me")) strcpy(w1,getmyname_jp());
- if (EQ(w1,"myself")) strcpy(w1,getmyname_jp());
- */
- pn=(OBJECT *) find_living_object(w1, 1); /* Find player by name */
- if (pn) {
- getfirst(cmd);
- if (gCarg) {
- free_svalue(gCarg->u.lvalue);
- gCarg->u.lvalue->type = T_OBJECT;
- gCarg->u.lvalue->u.ob = pn;
- add_ref(pn, "parse_command(%l)");
- }
- }
- return pn;
- }
-
- /* Find match to %p in pattern when a list of words has been supplied
- */
- int findword (cmd, v)
- char **cmd;
- VALUE *v;
- {
- char *w;
- VECTOR *p;
- struct svalue sv;
- int cnt,m,f;
-
- w = lookfirst(*cmd); lowercase(w); p=v->u.vec;
- cnt=0; m=p->size; f= -1;
- while (cnt<m) {
- if (p->item[cnt].type == T_STRING) {
- if (strcmp(p->item[cnt].u.string,w)==0) {
- f=cnt; cnt=m;
- }
- }
- cnt+=1;
- }
- if (f<0) return 0;
- getfirst(cmd);
- if (!f) return 1; /* Match and word in first element */
- /*
- Swap element 0 and f in array
- */
- sv=p->item[0]; p->item[0]=p->item[f]; p->item[f]=sv;
- return 1;
- }
-
- /* Find match to %p in pattern
- */
- int findprepos (cmd)
- char **cmd;
- {
- char *w;
- static char *hard_prep[] = {"on","in","under","from","behind","beside",0};
- SVALUE *v;
- int cnt;
-
- if (gForprepos) {
- v = gForprepos->u.lvalue;
- if ((v != 0) && (v->type == T_POINTER)) return findword(cmd,v);
- }
-
- /* No wordlist sent, use hard coded prepositions and return a string
- */
- w = lookfirst(*cmd); lowercase(w);
- cnt=0; while (hard_prep[cnt]) {
- if (strcmp(w,hard_prep[cnt])==0) {
- getfirst(cmd); /* Skip this word */
- if (gCarg) {
- free_svalue(gCarg->u.lvalue);
- gCarg->u.lvalue->type = T_STRING;
- gCarg->u.lvalue->u.string = string_copy(w);
- gCarg->u.lvalue->string_type = STRING_MALLOC;
- return 1;
- }
- }
- cnt++;
- }
- return 0;
- }
-
- /* Find match to %o in pattern
- */
- int findsingle (cmd)
- char **cmd;
- {
- if (finditem(cmd,0)) {
- if ((itnumalt()==1) && (gCarg)) {
- free_svalue(gCarg->u.lvalue);
- gCarg->u.lvalue->type = T_OBJECT;
- gCarg->u.lvalue->u.ob=italt(1);
- add_ref(gCarg->u.lvalue->u.ob, "parse_command(%o)");
- }
- return 1;
- }
- return 0;
- }
-
- /* Get the first parsetype of the pattern
- */
- int get1ps (parsep, lin, skip)
- char **parsep;
- LVALUE **lin;
- int skip;
- {
- char *cod,ch;
- int pt;
- LVALUE *l;
-
- pt=EP; cod=getfirst(parsep); l= *lin;
- ch=cod[0]; if (ch=='%') { ch=tolower(cod[1]); ch=cod[1]; }
- switch (ch) {
- case 'i':pt=IT; break;
- case 'l':pt=US; break;
- case 's':pt=TX; break;
- case 'w':pt=W1; break;
- case 'o':pt=SI; break;
- case 'p':pt=PP; break;
- case 'd':pt=NUM; break;
- case '\'':sscanf(cod,"'%[^\']",gMword); pt=DTX; break;
- case '[':sscanf(cod,"\[%[^\135]",gMword); pt=OTX; /* 135 is oct for ] */
- if (gMword[strlen(gMword)-1]==']') gMword[strlen(gMword)-1]=0;
- break;
- case '/':pt=ALT; break;
- }
- if (gDebug) fprintf(stderr,"(%s,%s,%d,%c)",cod,gMword,pt,ch);
- gCarg=0;
- if ((skip) || (pt==DTX) || (pt==OTX) || (pt==ALT)) return pt;
- if (l != gTopStack) { gForprepos=l; gCarg=l; l++; }
- else { gCarg = 0; gForprepos=0; }
- *lin=l;
- return pt;
- }
-
- /* Add word to the string that matches the latest %s
- */
- void addword (d, s)
- char *d;
- char *s;
- {
- if ((strlen(d)+strlen(s))<(KLUDGELEN-2)) {
- if (!EMPTY(d)) strcat(d," ");
- strcat(d,s);
- }
- if (gTxarg) {
- free_svalue(gTxarg->u.lvalue);
- gTxarg->u.lvalue->type = T_STRING;
- gTxarg->u.lvalue->u.string = string_copy(d);
- gTxarg->u.lvalue->string_type = STRING_MALLOC;
- }
- }
-
- /* Main function, called from interpret.c
- */
- int parse (cs, ob_or_array, ps, dest_args, num_arg)
- char *cs, *ps;
- struct svalue *ob_or_array, *dest_args;
- int num_arg;
- {
- /* Arguments:
- string Command
- ob/arr List of accessible objects or recurse start object
- ps parsepattern
- destargs lvalues.
- num_arg Number of lvalues.
- */
-
- int altflag, /* =1 (true) i altkedja, match har intr{ffat */
- txflag, /* = 1 om vi adderar text till str{ng */
- ptyp; /* Parsetype %o %i %l %p %s 'word' [word] / %w */
-
- char *parsep; /* Parsepattern */
- char *cmd; /* Command to be parsed */
- char *ops,*ocs; /* Temporary parse and command */
- char tx_jp[KLUDGELEN]; /* Fill up string for %s */
- LVALUE *l; /* Argument pointer in dest_args */
- int new_routines();
-
- if (ob_or_array->type == T_OBJECT &&
- (ob_or_array->u.ob->flags & O_DESTRUCTED))
- return 0;
- gDebug = 0;
- if (gDebug) {
- fprintf(stderr,"Hold on to your toes, entering JnAparse. ");
- }
-
-
- /* In mudlib 3.0 we will not have this
- */
- if (cs[0]=='@')
- error("Unsupported @ construct.\n");
-
- ocs = cmd = (char *) string_copy(cs);
-
- /* Get the accessible objects
- */
- if (ob_or_array->type == T_OBJECT) makeobjlist(&gOblist,ob_or_array->u.ob);
- else { /* Copy list of given accessible objects in reverse order */
- VECTOR *v;
- SVALUE *vv;
- int cnt;
- v=ob_or_array->u.vec; italt_new();
- for (cnt=0;cnt<v->size;cnt++) {
- vv = &(v->item[v->size-1-cnt]);
- if (vv->type==T_OBJECT) italt_put(vv->u.ob);
- }
- gOblist=gPobjects; gPobjects=0;
- }
-
- ops = parsep = (char *) string_copy(ps);
- gPobjects=gOblist;
- if (gDebug) fprintf(stderr,"Has made list of Acsobjects. %d \n",itnumalt());
- if (gDebug) fprintf(stderr,"Parsing: %s, with pattern: %s\n",cmd,parsep);
- gPobjects=0;
-
- /* Start parsing
- */
- txflag = -1; gCarg = 0; gTxarg = 0; gTopStack = dest_args + num_arg;
- l = dest_args;
-
- ptyp=get1ps(&parsep,&l,0); /* Get first pattern from parse */
-
- while (ptyp != EP) {
- if (gDebug) fprintf(stderr,"Pattern: %d\n",ptyp);
- altflag=0;
- switch(ptyp) { /* See which pattern type to search for */
-
- case EP: break;
-
- case SI: if (findsingle(&cmd)) altflag=1; /* %o */ break;
- case IT: if (findobject(&cmd)) altflag=1; /* %i */ break;
- case US: if (findplay(&cmd)) altflag=1; /* %l */ break;
- case PP: if (findprepos(&cmd)) altflag=1; /* %p */ break;
-
- case TX: /* %s */
- txflag=1; strcpy(tx_jp,""); gTxarg=gCarg; altflag=1;
- break;
-
- case DTX: /* 'word' */
- if (EQ(lowercase(gMword),lowercase(lookfirst(cmd)))) {
- getfirst(&cmd); altflag=1;
- }
- break;
-
- case OTX: /* [word] */
- if (EQ(lowercase(gMword),lowercase(lookfirst(cmd)))) {
- getfirst(&cmd);
- }
- altflag=1; /* Always take next parsepattern type [word] is opt */
- break;
-
- case ALT: /* / */
- altflag=1; /* Should not be found here, if so skip it */
-
- case W1: /* %w */
- gTxarg=gCarg; strcpy(tx_jp,""); altflag=1;
- addword(tx_jp,getfirst(&cmd));
- break;
-
- case NUM: /* %d */
- if ((altflag=numeric(lookfirst(cmd)))>0) {
- if (gCarg) {
- free_svalue(gCarg->u.lvalue);
- gCarg->u.lvalue->type = T_NUMBER;
- gCarg->u.lvalue->u.number = altflag;
- }
- altflag=1; getfirst(&cmd);
- }
- break;
- }
-
- /* Pattern checked altflag==1 indicates match
- */
- if (altflag) { /* Pattern matched, fetch next and end string input */
- if (ptyp != TX) txflag = -1; /* End string input if not just started */
- ptyp=get1ps(&parsep,&l,0);
- while (ptyp == ALT) { /* Skip left over alternatives */
- ptyp=get1ps(&parsep,&l,1); /* Skip this pattern */
- ptyp=get1ps(&parsep,&l,0); /* Next real pattern or ALT */
- }
- }
- else { /* Pattern did not match */
- char *a;
- LVALUE *try;
- int tmp;
- a=parsep; try=l;
- tmp=get1ps(&a,&try,0);
- if (tmp == ALT) {
- ptyp=get1ps(&parsep,&l,0); /* Skip ALT */
- ptyp=get1ps(&parsep,&l,0); /* Next real pattern or ALT */
- }
- else {
- if (txflag>=0) { /* %s is defined, add word and try pattern again */
- addword(tx_jp,getfirst(&cmd));
- }
- else break; /* Impossible to match pattern, exit */
- }
- }
-
- if (gDebug) fprintf(stderr,"Pattern, after: %d\n",ptyp);
- }
-
- /* End of pattern reached, what have got? What is left?
- */
- if (gDebug) fprintf(stderr,"Pattern ended\n");
-
- if (txflag>=0) { /* It ended with a %s, fill up the string */
- while (!EMPTY(cmd)) addword(tx_jp,getfirst(&cmd));
- }
-
- if (!EMPTY(cmd)) ptyp=ALT; /* No match so set ptyp != EP */
-
- /* Now clean up our mess, no alloced mem should remain
- */
- xfree(ocs); xfree(ops);
- if (gPobjects) italt_new(); /* Free alternate object list */
- if (gOblist) {
- gPobjects=gOblist; italt_new(); /* Free list of accessible objects */
- }
- if (ptyp==EP) {
- if (gDebug) fprintf(stderr,"Exiting Jnaparse with match\n");
- return 1; /* Successfull match */
- }
- else {
- if (gDebug) fprintf(stderr,"Exiting Jnaparse: No match\n");
- return 0; /* No match */
- }
- }
-
- /*
-
- End of Parser
-
- ***************************************************************/
-
- #endif
-